﻿using System;
using System.Collections.Generic;
using Core;
using Core.Model;
using Core.Model.Transmit;
using Core.Transmit;

namespace ModbusSlave
{
    public class ModbusDeviceProtocol:TransmitDeviceProtocol
    {
        private ModbusServer _modbusServer;
        private readonly Dictionary<string,TransmitData> transmitDatas = new Dictionary<string, TransmitData>();

        public override bool Initialize(TransmitChannelProtocol channel, TransmitDevice dev, List<TransmitData> dataItems)
        {
            base.Initialize(channel, dev, dataItems);
            _modbusServer = new ModbusServer();
            _modbusServer.SerialFlag = Channel.ChannelNetType == NetType.SerialPort;
            _modbusServer.UDPFlag = Channel.ChannelNetType == NetType.UdpServer ||
                                    Channel.ChannelNetType == NetType.UdpClient;
            _modbusServer.UnitIdentifier = (byte)Dev.Address;
            _modbusServer.HoldingRegistersChanged += _modbusServer_HoldingRegistersChanged;
            _modbusServer.CoilsChanged += _modbusServer_CoilsChanged;
            foreach (TransmitData data in dataItems)
            {
                transmitDatas[data.SourceId] = data;
            }
            Global.DataAccess.OnDataValueChanged += DataAccess_OnDataValueChanged;
            return true;
        }

        private bool _modbusServer_CoilsChanged(int coil, int numberOfCoils,byte function)
        {
            if (coil<0 || coil >= _modbusServer.coils.localArray.Length || numberOfCoils <= 0) return false;
            if (function == 0x05)
            {
                if (numberOfCoils != 1) return false;
                byte[] buffer = new byte[]{0,0};
                if (_modbusServer.coils[coil])
                {
                    buffer[0] = 0xFF;
                    buffer[1] = 0x00;
                }
                //Global.DataAccess.ModifyDataValue(Channel.ChlInfo.Id,Dev.Id,)
                
            }
           
            return false;
        }

        private bool _modbusServer_HoldingRegistersChanged(int register, int numberOfRegisters)
        {
            return false;
        }
        /// <summary>
        /// 数值变更
        /// </summary>
        /// <param name="itemId"></param>
        /// <param name="value"></param>
        /// <param name="triggerVal"></param>
        private void DataAccess_OnDataValueChanged(string itemId, object value, Int32 triggerVal)
        {
            try
            {
                if (transmitDatas.ContainsKey(itemId))
                {
                    TransmitData data = transmitDatas[itemId];
                    data.Value = value;
                   data.CurValue = (double)value;
                    if (data.PhyType == PhyType.模拟量)
                    {
                        _modbusServer.holdingRegisters[data.Address,2] =(Int32) (data.CurValue* data.Coefficient);
                    }
                    else if (data.PhyType == PhyType.信号量)
                    {
                        // ReSharper disable once RedundantCast
                        _modbusServer.coils[data.Address] = ((Int64)data.CurValue | (Int64)triggerVal) != 0;
                    }
                }
            }
            catch
            {  
            }
        }

        public override bool TryReplyCommand(byte[] clientBuffer, out byte[] replyBuffer)
        {
            replyBuffer = _modbusServer.ProcessReceivedData(clientBuffer);
            if (replyBuffer != null && replyBuffer.Length > 0) return true;
            return false;
        }
    }
}
